<!--  -->
<template>
  <div
    class="fixed z-50 pointer-events-none right-[23vw] -bottom-[6px] h-[378px] 3xl:right-[23.1vw] 8k:right-[6.95vw] w-[140px] overflow-hidden rounded-t-md"
  >
    <audio style="display: none" ref="audioElement" controls></audio>
    <div class="h-[130%] aspect-video right-0 bottom-0 absolute">
      <div class="size-full" id="DUIX"></div>
    </div>
  </div>
  <!-- <transition name="el-zoom-in-top">
    <div v-if="store.showDUIX" class="fixed top-2 left-28 z-50">
      <el-input
        @keydown.enter="answerQuestion"
        v-model="store.wordsDUIX"
        class="mx-2"
        style="width: 240px"
        placeholder="请输入提问"
      /><el-button type="success" @click="answerQuestion">提问</el-button>
    </div>
  </transition> -->
</template>

<script setup lang="ts">
import duixApi from '@/api/duix'
import { useCounterStore } from '@/stores/counter'
import DUIX, {
  type duixAnswerType,
  type duixGetAnswerResponseType,
  type duixGetAnswerType,
  type duixSpeakType
} from 'duix-guiji'
import { ElLoading, ElMessage } from 'element-plus'
import { storeToRefs } from 'pinia'
import { computed, onMounted, ref, watch } from 'vue'
// import ChartWords from './ChartWords.vue'
import { useRouter } from 'vue-router'
const store = useCounterStore()
const { showDUIX, openAsrDUIX, wordsDUIX, speechSumNumber } = storeToRefs(store)
const duix = new DUIX()
const router = useRouter()
const showBg = computed(() => {
  return router.currentRoute.value.query.showBg == 'transparent'
})
const initDUIX = (appId: string, sign: string) => {
  const loading = ElLoading.service({
    lock: true,
    text: '正在加载数字人主持，请稍后……',
    target: getBody.value,
    background: 'rgba(0, 0, 0, 0.0)'
  })
  duix.on('intialSucccess', () => {
    // 开始会话
    duix
      .start({
        conversationId: '1851614707194597378',
        openAsr: openAsrDUIX.value,
        muted: true,
        wipeGreen: false,
        transparent: showBg.value
      })
      .then((res) => {
        console.info(res)
      })
  })
  duix.on('bye', (data: string) => {
    console.info('bye', data)
  })
  duix.on('progress', (progress: number) => {
    console.info('progress', progress)
    loading.setText(`正在加载数字人主持 ${progress}%，请稍后……`)
  })
  duix.on('error', (data) => {
    console.error(data)
    ElMessage.error(data.data.message)
    loading.close()
    showDUIX.value = false
  })

  duix.on('show', () => {
    console.info('show')
    loading.close()
    duix.setVideoMuted(false)
  })
  duix.on('openAsrSuccess', () => {
    console.info('openAsrSuccess')
  })
  duix.on('asrClose', () => {
    console.info('asrClose')
  })
  duix.on('speakStart', (data) => {
    console.info('speakStart', data)
    isSpeaking.value = true
  })
  duix.on('speakEnd', (data) => {
    console.info('speakEnd', data)
    isSpeaking.value = false
    if (durationValInterval.value) {
      clearInterval(durationValInterval.value)
      durationValInterval.value = null
    }
  })
  duix.on('speakSection', (data) => {
    console.info('speakSection', data)
    if (isText.value) {
      audioDuration(data!.audio ?? '', data!.content)
    }
  })
  duix.on('speakError', (data) => {
    console.info('speakError', data)
  })

  //设置激活词 你好小吴
  let canAsk = false
  let asrResult = ''
  let timeWait: number | null

  let stopWord = ''

  setInterval(() => {
    if (
      stopWord.indexOf('介绍') > -1 ||
      stopWord.indexOf('讲解') > -1 ||
      stopWord.indexOf('政务服务') > -1 ||
      stopWord.indexOf('政务') > -1 ||
      stopWord.indexOf('大数据') > -1
    ) {
      console.info('监测到政务服务介绍关键词，开始播放本地文本')
      numDuration.value = 0
      speak_content()
      stopWord = ''
      return
    }

    if (
      stopWord.indexOf('暂停') > -1 ||
      stopWord.indexOf('等下') > -1 ||
      stopWord.indexOf('等一下') > -1
    ) {
      console.info(`识别到打断词，停止说话`)
      break_content()
      isSpeaking.value = false
      stopWord = ''
      return
    }

    if (stopWord.indexOf('继续') > -1) {
      console.info(`继续说话`)
      speak_content()
      stopWord = ''
      return
    }
  }, 1500)

  duix.on('asrResult', (data) => {
    console.info(data)
    stopWord += data
    //正常提问方法
    if (!canAsk) {
      if (data.indexOf('你好') > -1 || data.indexOf('小吴') > -1) {
        console.info('识别到唤haode醒词，开始记录接下来的文字')
        // 如果识别到唤醒词，那么就触发回答 并且开始计数
        const replyList = ['你好', '我在']
        duix_break()
        canAsk = true
        duix_speak({ content: replyList[Math.random() >= 0.5 ? 1 : 0] })
        timeWait = setTimeout(() => {
          console.info('十秒内无应答，停止唤醒')
          canAsk = false
          clearTimeout(timeWait!)
          timeWait = null
        }, 10000)
      }
    } else {
      console.log('记录识别语言……')
      if (timeWait) {
        console.log('存在定时器，将对1.5s定时器进行重置')
        clearTimeout(timeWait!)
        //文本叠加
        asrResult += data
        console.info(`识别文本叠加，叠加结果为${asrResult},本次叠加文本为“${data}”`)
        timeWait = setTimeout(() => {
          console.info(`定时器结束，开始执行answer逻辑`)
          //开始处理整合文本
          duix_break()
          console.info(`执行answer方法,question值为${asrResult}`)
          duix_answer({
            question: asrResult
          })
          console.log('清空asrResult，重置定时器')
          asrResult = ''
          canAsk = false
          clearTimeout(timeWait!)
          timeWait = null
        }, 1500)
      }
    }
  })
  duix.on('report', () => {
    // console.info("report", data)
  })
  // 初始化
  duix.init({
    sign: sign,
    containerLable: '#DUIX'
  })
}
const textContent = ref(
  `各位领导，下面介绍吴江区数据局政务服务大数据展示。本展示界面内容涵盖：政务服务办事大厅的分布、事项及分类、年度办件及板块办件情况，自助一体机分布和业务办理情况，建设项目投资，经营主体登记，公共资源交易，中介超市服务情况等。首先位于页面中间位置的是“吴江的区域板块图”，全域共有1个区级政务服务中心，12个便民服务中心和15个企业服务中心，以及154台政务服务自助一体机，为企业和群众提供线下办事服务。点击相应的板块，我们可以看到当日各办事点位的取号量以及在全区的占比情况，还接入了大厅摄像头数据，方便实时查看点位的现场情况。位于板块图下方展示的是“政务服务自助一体机”的相关数据。全区共投放154台政务服务自助一体机，主要分布在村社区、办事大厅、银行、警务站、大型企业、高校及高流量CBD中心等公共场所。一体机整合了人社、不动产、公积金、市民卡、水电气等多部门高频业务，同时打破时空限制和地域壁垒，实现与6省1市63个地区的一体机互联互通。在大屏左侧展示的是“计划投资项目情况”、“公共资源交易”“经营主体登记情况”。“计划投资项目情况”板块，展示的是近五年的立项项目数量及计划投资额，可以看到每年项目投资变化情况。点开二级目录，展示的是每月立项项目数量及计划投资额，通过对比，准确反映投资运行趋势，服务吴江区乃至苏州市高质量发展大局。三级目录展示的是每年项目明细，按照项目投资额由大到小进行排序，可以看到每个项目所处审批阶段，实时了解重点项目推进情况。“公共资源交易”板块，展示的是建设工程、交通工程、水利工程、政府采购、土地出让近3年交易情况。在交易数量上，政府采购项目数最多，今年以来，达683个；交易金额和节约资金额占比最大的是建设工程招投标项目，分别为125.29亿元和15.41亿元。这些数据直观呈现不同交易类型的规模和效益，为公共资源交易管理和决策提供有力支撑。“经营主体登记情况”板块，展示的是经营主体的存量数据和新增数据。目前吴江区经营主体登记事项由1个区级政务服务中心和7个便民服务中心办理，“全城通办”为企业和群众提供了更便捷的办事体验。经营主体类型共分为企业、个体工商户和农民专业合作社。从存量数据分析，个体工商户占存量市场主体数62.22%，企业占存量市场主体数37.61%，吴江区在册企业户数在苏州大市范围内排名第四。从新增数据分析，个体工商户占新增市场主体数61.99%，企业占存量市场主体数37.97%。在大屏右侧，“政务服务事项总览”板块，展示的是本年度政务服务事项总览情况，吴江全区共有2106项政务服务事项，包括6类权力事项和公共服务事项，占比情况如图所示。根据办理情况来看，其中即办件1524个，占比72％；承诺件582个，占比28％；“年度办件情况”板块，展示的是近三年来全区总体的办件情况，点开二级目录，可以查看各个乡镇、街道的年度详细办件情况。从折线图上来看，每年的3月、8月左右业务量较大，可提前做好窗口人员的规划和分流，保证大厅高效运转；“中介超市服务情况”板块，展示的是吴江区网上中介超市运行情况，根据平台运行以来的累计数据来看，目前热门项目主要集中在造价咨询、政府采购代理、建设(人防)工程招标代理、房产评估、建筑(人防)工程质量检测这五类，其中累计完成造价咨询类交易项目${speechSumNumber.value.right3.consult}个，政府采购代理类项目${speechSumNumber.value.right3.business}个。从入驻的机构来看，目前主要集中在房产经纪、货运代理、政府采购代理、会计代理记账服务、建设（人防）工程招标代理这5类，其中热门机构如房产经纪${speechSumNumber.value.right3.building}家、货运代理${speechSumNumber.value.right3.order}家等。以上就是一个简单的情况介绍，感谢您的聆听！`
)
watch(
  speechSumNumber,
  (newVal) => {
    textContent.value = `各位领导，下面介绍吴江区数据局政务服务大数据展示。本展示界面内容涵盖：政务服务办事大厅的分布、事项及分类、年度办件及板块办件情况，自助一体机分布和业务办理情况，建设项目投资，经营主体登记，公共资源交易，中介超市服务情况等。首先位于页面中间位置的是“吴江的区域板块图”，全域共有1个区级政务服务中心，12个便民服务中心和15个企业服务中心，以及154台政务服务自助一体机，为企业和群众提供线下办事服务。点击相应的板块，我们可以看到当日各办事点位的取号量以及在全区的占比情况，还接入了大厅摄像头数据，方便实时查看点位的现场情况。位于板块图下方展示的是“政务服务自助一体机”的相关数据。全区共投放154台政务服务自助一体机，主要分布在村社区、办事大厅、银行、警务站、大型企业、高校及高流量CBD中心等公共场所。一体机整合了人社、不动产、公积金、市民卡、水电气等多部门高频业务，同时打破时空限制和地域壁垒，实现与6省1市63个地区的一体机互联互通。在大屏左侧展示的是“计划投资项目情况”、“公共资源交易”“经营主体登记情况”。“计划投资项目情况”板块，展示的是近五年的立项项目数量及计划投资额，可以看到每年项目投资变化情况。点开二级目录，展示的是每月立项项目数量及计划投资额，通过对比，准确反映投资运行趋势，服务吴江区乃至苏州市高质量发展大局。三级目录展示的是每年项目明细，按照项目投资额由大到小进行排序，可以看到每个项目所处审批阶段，实时了解重点项目推进情况。“公共资源交易”板块，展示的是建设工程、交通工程、水利工程、政府采购、土地出让近3年交易情况。在交易数量上，政府采购项目数最多，今年以来，达683个；交易金额和节约资金额占比最大的是建设工程招投标项目，分别为125.29亿元和15.41亿元。这些数据直观呈现不同交易类型的规模和效益，为公共资源交易管理和决策提供有力支撑。“经营主体登记情况”板块，展示的是经营主体的存量数据和新增数据。目前吴江区经营主体登记事项由1个区级政务服务中心和7个便民服务中心办理，“全城通办”为企业和群众提供了更便捷的办事体验。经营主体类型共分为企业、个体工商户和农民专业合作社。从存量数据分析，个体工商户占存量市场主体数62.22%，企业占存量市场主体数37.61%，吴江区在册企业户数在苏州大市范围内排名第四。从新增数据分析，个体工商户占新增市场主体数61.99%，企业占存量市场主体数37.97%。在大屏右侧，“政务服务事项总览”板块，展示的是本年度政务服务事项总览情况，吴江全区共有2106项政务服务事项，包括6类权力事项和公共服务事项，占比情况如图所示。根据办理情况来看，其中即办件1524个，占比72％；承诺件582个，占比28％；“年度办件情况”板块，展示的是近三年来全区总体的办件情况，点开二级目录，可以查看各个乡镇、街道的年度详细办件情况。从折线图上来看，每年的3月、8月左右业务量较大，可提前做好窗口人员的规划和分流，保证大厅高效运转；“中介超市服务情况”板块，展示的是吴江区网上中介超市运行情况，根据平台运行以来的累计数据来看，目前热门项目主要集中在造价咨询、政府采购代理、建设(人防)工程招标代理、房产评估、建筑(人防)工程质量检测这五类，其中累计完成造价咨询类交易项目${newVal.right3.consult}个，政府采购代理类项目${newVal.right3.business}个。从入驻的机构来看，目前主要集中在房产经纪、货运代理、政府采购代理、会计代理记账服务、建设（人防）工程招标代理这5类，其中热门机构如房产经纪${newVal.right3.building}家、货运代理${newVal.right3.order}家等。以上就是一个简单的情况介绍，感谢您的聆听！`
  },
  { deep: true }
)

const duix_break = () => {
  duix.break()
}

const break_content = () => {
  duix.break() //打断数字人说话
  if (durationValInterval.value) {
    clearInterval(durationValInterval.value)
    durationValInterval.value = null
  }
  let num = Math.ceil(sVal.value * numDuration.value) - 1
  let toal = filterPunctuationMarks(textContent.value).length
  let text = filterPunctuationMarks(textContent.value)
  let newText = ''
  isText.value = false
  for (let i = num; i < toal; i++) {
    newText = newText + (text[i] ?? '')
  }
  console.log(`当前位置${num},文本总长度${toal},未播文本${newText}`)
  textContent.value = newText
}

const duix_speak = (option: duixSpeakType) => {
  return duix.speak(option) //驱动数字人说话，支持文本驱动和音频文件驱动
}

const duix_answer = (option: duixAnswerType) => {
  if (option.question.indexOf('暂停') > -1) {
    duix_break()
    isSpeaking.value = false
    return
  }
  duix.answer(option)
}

const duix_get_answer = (option: duixGetAnswerType): Promise<duixGetAnswerResponseType> => {
  return duix.getAnswer(option)
}
//开始录音
const duix_startRecord = () => {
  return duix.startRecord()
}
//结束录音，录音成功后将返加语音识别结果（文本），返回Promise
const duix_stopRecord = () => {
  return duix.stopRecord()
}
//开启语音实时识别(注意此方法需在show触发时候调用)。开启语音实时识别后，可通过监听 asrResult 事件，接收识别（文本）结果
const duix_openAsr = () => {
  return duix.openAsr()
}
//关闭语音实时识别
const duix_closeAsr = () => {
  return duix.closeAsr()
}
//停止当前会话，与start成对。建议在页卸载事件中调用此方法，以防止刷新或关闭网页时当前会话资源未及时释放
const duix_stop = () => {
  return duix.stop()
}
//销毁duix实例，与init成对。destroy后需重新init
const duix_destroy = () => {
  return duix.destroy()
}
//获取本地语音流，方便外部做音频可视化等功能
const duix_getLocalStream = () => {
  return duix.getLocalStream()
}
//获取远端音视频流，方便外部做自定义
const duix_getRemoteStream = () => {
  return duix.getRemoteStream()
}

const duixListener = () => {}

watch(showDUIX, (val) => {
  if (val) {
    duixApi.getDUIXSign().then((res) => {
      initDUIX(res.appId, res.sign)
    })
  } else {
    if (!duix) return
    duix_destroy()
  }
})

const isSpeaking = ref(false)

const audioElement = ref<HTMLAudioElement>()
const durationVal = ref(0)
const sVal = ref(0)
const numDuration = ref(0)
const durationValInterval = ref<null | number>(null)
const isText = ref(false)

const audioDuration = (audio: string, content: string) => {
  const audioUrl = audio
  audioElement.value!.src = audioUrl
  audioElement.value!.addEventListener('loadedmetadata', () => {
    // 获取音频时长
    const duration = audioElement.value!.duration
    durationVal.value = Math.floor(duration * 100) / 100
    sVal.value = filterPunctuationMarks(content).length / durationVal.value
    console.log('文本存储', sVal.value)
  })
  // 加载音频
  audioElement.value!.load()
  numDuration.value = 0
  durationValInterval.value = setInterval(() => {
    numDuration.value = numDuration.value + 1
  }, 1000)
}

const filterPunctuationMarks = (text: string) => {
  return text.replace(/[.,。，、*：/#!$%^&*;:{}=\-_`~()|[\]<>?"'“”‘’：:]/g, '')
}

const answerQuestion = () => {
  if (wordsDUIX.value == '请介绍一下政务服务大数据') {
    numDuration.value = 0
    speak_content()
  } else if (
    wordsDUIX.value.indexOf('暂停') > -1 ||
    wordsDUIX.value.indexOf('等下') > -1 ||
    wordsDUIX.value.indexOf('等一下') > -1
  ) {
    break_content()
  } else if (wordsDUIX.value.indexOf('继续') > -1) {
    speak_content()
  } else {
    duix_answer({ question: wordsDUIX.value })
  }
}

const speak_content = () => {
  duix.break()
  isText.value = true
  if (durationValInterval.value) clearInterval(durationValInterval.value)
  if (filterPunctuationMarks(textContent.value)) {
    duix.speak({
      content: '好的，' + textContent.value
    })
  }
}

const getBody = computed(() => {
  const dom = document.getElementById('dom-scale')
  return dom ?? 'body'
})

let canclick = false
onMounted(() => {
  document.addEventListener('keydown', function (e) {
    if (e.keyCode == 18) {
      canclick = true
    }
    if (canclick) {
      console.log(`键名: ${e.key}, 键码: `, e.keyCode)
      switch (e.keyCode) {
        case 48:
          duix_break()
          break
        case 49:
          duix_answer({ question: '1' })
          break
        case 50:
          duix_answer({ question: '2' })
          break
        case 51:
          duix_answer({ question: '3' })
          break
        case 52:
          duix_answer({ question: '4' })
          break
        case 53:
          duix_answer({ question: '5' })
          break
        case 54:
          duix_answer({ question: '6' })
          break
        case 55:
          duix_answer({ question: '7' })
          break
        case 56:
          duix_answer({ question: '8' })
          break
        case 57:
          duix_answer({ question: '9' })
          break
        case 75:
          speak_content()
          break
        default:
          break
      }
    }
  })

  document.addEventListener('keyup', function (e) {
    if (e.keyCode == 18) {
      canclick = false
    }
  })
})
</script>
<style scoped lang="less">
/* @import url(); 引入css类 */
</style>
